﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WBug
{
    public partial class MainForm : Form
    {
        #region 字段、属性

        private HtmlAgilityPack.HtmlDocument htmlDoc;
        private WebClient webClient;
        private FileStream fileStream;
        private StreamWriter streamWriter;
        private WebBrowser webBrowser1;
        private System.Timers.Timer timer = new System.Timers.Timer();

        private readonly string fileNameSuffix = "基金信息";
        private string filePath = @"D:";
        private string fileName;
        private string status;
        private uint pageCount;
        private uint pageNum;
        private uint tarPageNum;
        private bool IsFirstRun;
        private bool IsParseCompleted;

        #endregion 字段、属性


        public MainForm()
        {
            InitializeComponent();

            webBrowser1 = webBrowser;
            fileName = fileNameSuffix + DateTime.Now.ToString("yyyyMMdd") + ".xls";
            PrintStatusInfo();
            htmlDoc = new HtmlAgilityPack.HtmlDocument();
            webClient = new WebClient();
            status = "未开始";
            pageCount = 0;
            pageNum = 1;
            tarPageNum = 1;
            IsFirstRun = true;
            IsParseCompleted = true;
        }

        // 开始按钮点击后触发
        private void startButton_Click(object sender, EventArgs e)
        {
            if (IsFirstRun) {
                IsFirstRun = false;
                pageCount = 5;// GetPageCount();
                fileStream = File.Open(filePath + @"\" + fileName, FileMode.Append, FileAccess.Write);
                streamWriter = new StreamWriter(fileStream);
            }
            setFileButton.Enabled = false;
            startButton.Enabled = false;
            pauseButton.Enabled = true;
            startButton.Text = "继续";
            status = "运行中";
            pageCount = GetPageCount();
            tarPageNum = pageNum = GetPageNum();
            PrintStatusInfo();

            timer.Elapsed += new System.Timers.ElapsedEventHandler(RunParse);
            timer.Interval = 1000;
            timer.AutoReset = true;
            timer.Enabled = true;

        }

        // 修改保存位置按钮点击后触发
        private void setFilePathButton_Click(object sender, EventArgs e)
        {
            var dialog = new FolderBrowserDialog
            {
                Description = "请选择文件保存位置"
            };
            if (dialog.ShowDialog() == DialogResult.OK) {
                if (string.IsNullOrEmpty(dialog.SelectedPath)) {
                    MessageBox.Show(this, "文件夹路径不能为空！", "提示");
                    return;
                }
                filePath = dialog.SelectedPath;
                PrintStatusInfo();
            }
        }

        // 暂停按钮点击后触发
        private void pauseButton_Click(object sender, EventArgs e)
        {
            pauseButton.Enabled = false;
            startButton.Enabled = true;
            timer.Stop();
            status = "已暂停";
            PrintStatusInfo();
        }

        // 窗体关闭时触发
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            timer.Stop();
            var tempSW = streamWriter;
            var tempFS = fileStream;
            streamWriter = null;
            fileStream = null;
            tempSW?.Flush();
            tempSW?.Close();
            tempSW?.Dispose();
            tempFS?.Close();
            tempFS?.Dispose();
        }

        // 解析
        private void RunParse(object source, System.Timers.ElapsedEventArgs e)
        {
            if (tarPageNum == pageCount + 1) {
                timer.Stop();
                this.Invoke(new MethodInvoker(delegate { status = "已完成！"; PrintStatusInfo(); }));
                return;
            }
            if (IsParseCompleted && (pageNum = GetPageNum()) == tarPageNum) {
                this.Invoke(new MethodInvoker(delegate {
                    PrintStatusInfo();
                    var atags = this.webBrowser1.Document.GetElementById("fundlist").GetElementsByTagName("A");
                    Task.Run(() =>
                    {
                        ParsePage(atags);
                        this.Invoke(new MethodInvoker(delegate { GoToNextPage(); }));
                    });
                }));
                ++tarPageNum;
            }
        }

        // 输出状态信息
        private void PrintStatusInfo()
        {
            string statusInfo = "文件存放路径：" + filePath + @"\" + fileName + "\r\n";
            statusInfo += "总页数：" + pageCount + "\r\n";
            statusInfo += "当前页数：" + pageNum + "\r\n";
            statusInfo += "状态：" + status;
            this.infoTextBox.Text = statusInfo;
        }

        // 翻页
        private void GoToNextPage()
        {
            HtmlElement script = this.webBrowser1.Document.CreateElement("script");
            script.SetAttribute("type", "text/javascript");
            script.SetAttribute("text", "function _func(){$('.next').click()}");
            HtmlElement head = this.webBrowser1.Document.Body.AppendChild(script);
            this.webBrowser1.Document.InvokeScript("_func");
            this.webBrowser1.Document.Body.InvokeMember("MouseDown");
            this.webBrowser1.Document.Body.InvokeMember("MouseUp");
            this.webBrowser1.Document.Body.InvokeMember("MouseOver");
            this.webBrowser1.Document.Body.InvokeMember("MouseMove");
            this.webBrowser1.Update();

            //var atags = document.GetElementById("fundlist_paginate").GetElementsByTagName("A");
            //foreach (HtmlElement atag in atags) {
            //    if (atag.GetAttribute("className") == "paginate_button next") {
            //        atag.InvokeMember("onclick");
            //        Console.WriteLine(document.GetElementById("fundlist").InnerText);
            //        break;
            //    }
            //}

        }

        // 获取总页数
        private uint GetPageCount()
        {
            var innerText = this.webBrowser1.Document.GetElementById("fundlist_info").InnerText;
            var numStr = innerText.Substring(innerText.LastIndexOf("共") + 1, innerText.LastIndexOf("页") - innerText.LastIndexOf("共") - 1);
            return uint.Parse(numStr);
        }

        // 获取当前页码
        private uint GetPageNum()
        {
            HtmlElementCollection atags = null;
            this.Invoke(new MethodInvoker(delegate {
                atags = this.webBrowser.Document.GetElementById("fundlist_paginate").GetElementsByTagName("A");
            }));
            if (atags != null) {
                foreach (HtmlElement atag in atags) {
                    if (atag.GetAttribute("className") == "paginate_button paginate_number current") {
                        return uint.Parse(atag.InnerText);
                    }
                }
            }
            return 0;
        }

        // 解析当前页
        private void ParsePage(HtmlElementCollection atags)
        {
            IsParseCompleted = false;
            //var atags = this.webBrowser1.Document.GetElementById("fundlist").GetElementsByTagName("A");
            foreach (HtmlElement atag in atags) {
                if (atag.GetAttribute("href").Contains("fund")) {
                    ParseFundInfo(atag.GetAttribute("href"));
                }
            }
            IsParseCompleted = true;
        }

        // 获取基金详情
        private void ParseFundInfo(string url)
        {
            string strHTML = "";
            Stream myStream = webClient.OpenRead(url);
            StreamReader sr = new StreamReader(myStream, Encoding.GetEncoding("utf-8"));
            strHTML = sr.ReadToEnd();
            myStream.Close();
            sr.Dispose();

            htmlDoc.LoadHtml(strHTML);
            var trNodes = htmlDoc.DocumentNode.SelectNodes(".//tr");

            foreach (var trnode in trNodes) {
                if (trnode.ChildNodes.Count > 3) {
                    //var title = trnode.ChildNodes[1].InnerText;
                    var content = trnode.ChildNodes[3].InnerText.Replace('\r', ' ').Replace('\n', ' ').Trim();
                    streamWriter?.Write(content);
                    streamWriter?.Write("\t");
                }
            }
            streamWriter?.Write("\n");
            streamWriter?.Flush();
        }

    }
}